package com.gec.anan.customer.service.impl;

import com.gec.anan.common.execption.AnanException;
import com.gec.anan.common.result.ResultCodeEnum;
import com.gec.anan.coupon.client.CouponFeignClient;
import com.gec.anan.customer.client.CustomerInfoFeignClient;
import com.gec.anan.customer.service.OrderService;
import com.gec.anan.dispatch.client.NewOrderFeignClient;
import com.gec.anan.driver.client.DriverInfoFeignClient;
import com.gec.anan.map.client.LocationFeignClient;
import com.gec.anan.map.client.MapFeignClient;
import com.gec.anan.map.client.WxPayFeignClient;
import com.gec.anan.model.entity.order.OrderInfo;
import com.gec.anan.model.enums.OrderStatus;
import com.gec.anan.model.form.coupon.UseCouponForm;
import com.gec.anan.model.form.customer.ExpectOrderForm;
import com.gec.anan.model.form.customer.SubmitOrderForm;
import com.gec.anan.model.form.map.CalculateDrivingLineForm;
import com.gec.anan.model.form.order.OrderInfoForm;
import com.gec.anan.model.form.payment.CreateWxPaymentForm;
import com.gec.anan.model.form.payment.PaymentInfoForm;
import com.gec.anan.model.form.rules.FeeRuleRequestForm;
import com.gec.anan.model.vo.base.PageVo;
import com.gec.anan.model.vo.customer.ExpectOrderVo;
import com.gec.anan.model.vo.dispatch.NewOrderTaskVo;
import com.gec.anan.model.vo.driver.DriverInfoVo;
import com.gec.anan.model.vo.map.DrivingLineVo;
import com.gec.anan.model.vo.map.OrderLocationVo;
import com.gec.anan.model.vo.map.OrderServiceLastLocationVo;
import com.gec.anan.model.vo.order.CurrentOrderInfoVo;
import com.gec.anan.model.vo.order.OrderBillVo;
import com.gec.anan.model.vo.order.OrderInfoVo;
import com.gec.anan.model.vo.order.OrderPayVo;
import com.gec.anan.model.vo.payment.WxPrepayVo;
import com.gec.anan.model.vo.rules.FeeRuleResponseVo;
import com.gec.anan.order.client.OrderInfoFeignClient;
import com.gec.anan.rules.client.FeeRuleFeignClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;

@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class OrderServiceImpl implements OrderService {

    @Autowired
    private MapFeignClient mapFeignClient;

    @Autowired
    private FeeRuleFeignClient feeRuleFeignClient;

    @Autowired
    private OrderInfoFeignClient orderInfoFeignClient;

    @Autowired
    private NewOrderFeignClient newOrderFeignClient;
    @Autowired
    private DriverInfoFeignClient driverInfoFeignClient;

    @Autowired
    private LocationFeignClient locationFeignClient;

    @Autowired
    private CustomerInfoFeignClient customerInfoFeignClient;
    @Autowired
    private WxPayFeignClient wxPayFeignClient;

    @Autowired
    private CouponFeignClient couponFeignClient;

    /**
     * 计算订单数据
     *
     * @param expectOrderForm
     * @return
     */
    @Override
    public ExpectOrderVo expectOrder(ExpectOrderForm expectOrderForm) {
        log.info("计算费用:{}", expectOrderForm);
        CalculateDrivingLineForm calculateDrivingLineForm = new CalculateDrivingLineForm();
        BeanUtils.copyProperties(expectOrderForm, calculateDrivingLineForm);
        //获取驾驶路线
        DrivingLineVo drivingLineVo = mapFeignClient.calculateDrivingLine(calculateDrivingLineForm).getData();
        if (drivingLineVo == null) {
            throw new AnanException(ResultCodeEnum.DATA_ERROR);
        }
        //封装计算参数
        FeeRuleRequestForm ruleRequestForm = new FeeRuleRequestForm();
        ruleRequestForm.setDistance(drivingLineVo.getDistance());
        ruleRequestForm.setWaitMinute(0);
        ruleRequestForm.setStartTime(new Date());
        //计算费用
        FeeRuleResponseVo ruleResponseVo = feeRuleFeignClient.calculateOrderFee(ruleRequestForm).getData();
        if (ruleResponseVo == null) {
            throw new AnanException(ResultCodeEnum.DATA_ERROR);
        }
        //封装成ExpectOrderVo对象
        ExpectOrderVo expectOrderVo = new ExpectOrderVo();
        expectOrderVo.setDrivingLineVo(drivingLineVo);
        expectOrderVo.setFeeRuleResponseVo(ruleResponseVo);
        return expectOrderVo;
    }

    /**
     * 乘客下单
     *
     * @param submitOrderForm
     * @return
     */
    @Override
    public Long saveOrder(SubmitOrderForm submitOrderForm) {
        //重新计算驾驶路线
        CalculateDrivingLineForm calculateDrivingLineForm = new CalculateDrivingLineForm();
        BeanUtils.copyProperties(submitOrderForm, calculateDrivingLineForm);
        DrivingLineVo drivingLineVo = mapFeignClient.calculateDrivingLine(calculateDrivingLineForm).getData();
        if (drivingLineVo == null) {
            throw new AnanException(ResultCodeEnum.MAP_FAIL);
        }
        //重新计算费用
        FeeRuleRequestForm ruleRequestForm = new FeeRuleRequestForm();
        ruleRequestForm.setWaitMinute(0);
        ruleRequestForm.setDistance(drivingLineVo.getDistance());
        ruleRequestForm.setStartTime(new Date());
        FeeRuleResponseVo feeRuleResponseVo = feeRuleFeignClient.calculateOrderFee(ruleRequestForm).getData();
        if (feeRuleResponseVo == null) {
            throw new AnanException(ResultCodeEnum.FEIGN_FAIL);
        }
        //封装远程调用的参数
        OrderInfoForm orderInfo = new OrderInfoForm();
        BeanUtils.copyProperties(submitOrderForm, orderInfo);
        log.info("远程调用参数{}", orderInfo);
        orderInfo.setExpectAmount(feeRuleResponseVo.getTotalAmount());
        orderInfo.setExpectDistance(drivingLineVo.getDistance());
        //调用并返回id
        Long orderId = orderInfoFeignClient.saveOrderInfo(orderInfo).getData();

        //任务调度.每分钟执行一次搜索附近的司机
        //5.1.封装调度参数对象
        NewOrderTaskVo newOrderDispatchVo = new NewOrderTaskVo();
        newOrderDispatchVo.setOrderId(orderId);
        newOrderDispatchVo.setStartLocation(orderInfo.getStartLocation());
        newOrderDispatchVo.setStartPointLongitude(orderInfo.getStartPointLongitude());
        newOrderDispatchVo.setStartPointLatitude(orderInfo.getStartPointLatitude());
        newOrderDispatchVo.setEndLocation(orderInfo.getEndLocation());
        newOrderDispatchVo.setEndPointLongitude(orderInfo.getEndPointLongitude());
        newOrderDispatchVo.setEndPointLatitude(orderInfo.getEndPointLatitude());
        newOrderDispatchVo.setExpectAmount(orderInfo.getExpectAmount());
        newOrderDispatchVo.setExpectDistance(orderInfo.getExpectDistance());
        newOrderDispatchVo.setExpectTime(drivingLineVo.getDuration());
        newOrderDispatchVo.setFavourFee(orderInfo.getFavourFee());
        newOrderDispatchVo.setCreateTime(new Date());
        //远程调用
        Long jobId = newOrderFeignClient.addAndStartTask(newOrderDispatchVo).getData();
        return orderId;
    }

    /**
     * 获取订单id
     *
     * @param orderId
     * @return
     */
    @Override
    public Integer getOrderStatus(Long orderId) {
        Integer orderStatus = orderInfoFeignClient.getOrderStatus(orderId).getData();
        if (orderStatus == null) {
            throw new AnanException(ResultCodeEnum.FEIGN_FAIL);
        }
        return orderStatus;
    }

    /**
     * 查找当前乘客订单
     *
     * @param customerId
     * @return
     */
    @Override
    public CurrentOrderInfoVo searchCustomerCurrentOrder(Long customerId) {
        return orderInfoFeignClient.searchCustomerCurrentOrder(customerId).getData();
    }

    //根据订单id获取详情
    @Override
    public OrderInfoVo getOrderInfo(Long orderId, Long customerId) {
        OrderInfo orderInfo = orderInfoFeignClient.getOrderInfo(orderId).getData();
        if (orderInfo.getCustomerId().longValue() != customerId.longValue()) {
            throw new AnanException(ResultCodeEnum.ILLEGAL_REQUEST);
        }
        //获取司机信息
        DriverInfoVo driverInfoVo = null;
        if (null != orderInfo.getDriverId()) {
            driverInfoVo = driverInfoFeignClient.getDriverInfo(orderInfo.getDriverId()).getData();
        }

        //账单信息
        OrderBillVo orderBillVo = null;
        if (orderInfo.getStatus().intValue() >= OrderStatus.UNPAID.getStatus().intValue()) {
            orderBillVo = orderInfoFeignClient.getOrderBillInfo(orderId).getData();
        }
        System.out.println("乘客订单详情");
        OrderInfoVo orderInfoVo = new OrderInfoVo();
        orderInfoVo.setOrderId(orderId);
        BeanUtils.copyProperties(orderInfo, orderInfoVo);
        orderInfoVo.setOrderBillVo(orderBillVo);
        orderInfoVo.setDriverInfoVo(driverInfoVo);
        return orderInfoVo;
    }

    //根据订单id获取司机基本信息
    @Override
    public DriverInfoVo getDriverInfo(Long orderId, Long customerId) {
        //获取订单详情
        OrderInfo orderInfo = orderInfoFeignClient.getOrderInfo(orderId).getData();
        if (orderInfo.getCustomerId().longValue() != customerId.longValue()) {
            throw new AnanException(ResultCodeEnum.ILLEGAL_REQUEST);
        }

        return driverInfoFeignClient.getDriverInfo(orderInfo.getDriverId()).getData();
    }

    //获取司机位置信息
    @Override
    public OrderLocationVo getCacheOrderLocation(Long orderId) {
        return locationFeignClient.getCacheOrderLocation(orderId).getData();
    }

    //司乘同显
    @Override
    public DrivingLineVo calculateDrivingLine(CalculateDrivingLineForm calculateDrivingLineForm) {
        return mapFeignClient.calculateDrivingLine(calculateDrivingLineForm).getData();
    }

    @Override
    public OrderServiceLastLocationVo getOrderServiceLastLocation(Long orderId) {
        return locationFeignClient.getOrderServiceLastLocation(orderId).getData();
    }

    //根据乘客id查找订单列表
    @Override
    public PageVo findCustomerOrderPage(Long customerId, Long page, Long limit) {
        return orderInfoFeignClient.findCustomerOrderPage(customerId, page, limit).getData();
    }

    //乘客调取微信支付接口
    @Override
    public WxPrepayVo createWxPayment(CreateWxPaymentForm createWxPaymentForm) {
        //获取支付信息
        OrderPayVo orderPayVo = orderInfoFeignClient.getOrderPayVo(createWxPaymentForm.getOrderNo(),
                createWxPaymentForm.getCustomerId()).getData();
        log.info("订单参数{}", orderPayVo);
        //判断是否是未支付
        if (orderPayVo.getStatus().intValue() != OrderStatus.UNPAID.getStatus().intValue()) {
            throw new AnanException(ResultCodeEnum.ILLEGAL_REQUEST);
        }
        //获取乘客司机openid
        String customerOpenId = customerInfoFeignClient.getCustomerOpenId(orderPayVo.getCustomerId()).getData();
        String driverOpenId = driverInfoFeignClient.getDriverOpenId(orderPayVo.getDriverId()).getData();
        //4.处理优惠券
        BigDecimal couponAmount = null;
        //支付时选择过一次优惠券，如果支付失败或未支付，下次支付时不能再次选择，只能使用第一次选中的优惠券（前端已控制，后端再次校验）
        if (null == orderPayVo.getCouponAmount() && null != createWxPaymentForm.getCustomerCouponId() && createWxPaymentForm.getCustomerCouponId() != 0) {
            UseCouponForm useCouponForm = new UseCouponForm();
            useCouponForm.setOrderId(orderPayVo.getOrderId());
            useCouponForm.setCustomerCouponId(createWxPaymentForm.getCustomerCouponId());
            useCouponForm.setOrderAmount(orderPayVo.getPayAmount());
            useCouponForm.setCustomerId(createWxPaymentForm.getCustomerId());
            couponAmount = couponFeignClient.useCoupon(useCouponForm).getData();
        }

        //5.更新账单优惠券金额
        //支付金额
        BigDecimal payAmount = orderPayVo.getPayAmount();
        if (null != couponAmount) {
            log.info("订单id{}", orderPayVo.getOrderId());
            Boolean isUpdate = orderInfoFeignClient.updateCouponAmount(orderPayVo.getOrderId(), couponAmount).getData();
            if (!isUpdate) {
                throw new AnanException(ResultCodeEnum.DATA_ERROR);
            }
            //当前支付金额 = 支付金额 - 优惠券金额
            payAmount = payAmount.subtract(couponAmount);
        }
        //封装参数发起支付
        PaymentInfoForm paymentInfoForm = new PaymentInfoForm();
        paymentInfoForm.setOrderNo(orderPayVo.getOrderNo());
        paymentInfoForm.setAmount(payAmount);
        paymentInfoForm.setDriverOpenId(driverOpenId);
        paymentInfoForm.setCustomerOpenId(customerOpenId);
        paymentInfoForm.setContent(orderPayVo.getContent());
        paymentInfoForm.setPayWay(1);
        WxPrepayVo wxPrepayVo = wxPayFeignClient.createWxPayment(paymentInfoForm).getData();

        return wxPrepayVo;
    }

    //查询支付状态
    @Override
    public Boolean queryPayStatus(String orderNo) {
        return wxPayFeignClient.queryPayStatus(orderNo).getData();
    }

}
